package com.qixin.activiti.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qixin.activiti.service.IEaPaymentBXNCItfService;
import com.qixin.activiti.utils.EaListenerUtil;
import com.qixin.modules.ea.entity.EaBookDetail;
import com.qixin.modules.ea.entity.EaPayment;
import com.qixin.modules.ea.service.IEaBookDetailService;
import com.qixin.modules.ea.service.IEaPaymentService;
import com.qixin.modules.log.entity.SysInterfaceLog;
import com.qixin.modules.rzInvoice.service.IEaBillService;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.nc.enums.WSEnum;
import org.jeecg.common.nc.service.NCWebService;
import org.jeecg.common.nc.vo.WSVO;
import org.jeecg.modules.activiti.entity.ActBusiness;
import org.jeecg.modules.activiti.entity.ActZTask;
import org.jeecg.modules.activiti.service.IActZTaskService;
import org.jeecg.modules.nc.service.INcBdPsnjobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/***
* @Description: 资金审批单推送NC报销审核通过接口
* @author: CYS
* @date: 2022/3/15 11:32
*/
@Slf4j
@Service
public class EaPaymentBXNCItfServiceImpl implements IEaPaymentBXNCItfService {


    @Autowired
    private IEaPaymentService iEaPaymentService;
    @Autowired
    private IEaBookDetailService eaBookDetailService;
    @Autowired
    private IEaBillService iEaBillService;
    @Autowired
    private IActZTaskService iActZTaskService;
    @Autowired
    private INcBdPsnjobService iNcBdPsnjobService;
    @Value(value = "${qixin.ncserver.uri}")
    private  String nCUrl;



    @Override
    public SysInterfaceLog bXApprove(ActBusiness actBusiness, String billNo) throws Exception {
        SysInterfaceLog sysInterfaceLog = new SysInterfaceLog();
        sysInterfaceLog.setBusinessNo(billNo);

            //查询资金审批单报销头
            EaPayment eaPayment = iEaPaymentService.getById(actBusiness.getTableId());
            if(null==eaPayment){
                throw new RuntimeException("根据"+actBusiness.getTableId()+"TableId查询资金审批单空！");
            }
            EaListenerUtil.objectDefault(eaPayment,EaPayment.class);

            //查询资金审批单表体费用明细
            List<EaBookDetail> eaBookDetails = eaBookDetailService.selectByMainId(eaPayment.getId());
            if(null==eaBookDetails||eaBookDetails.size()==0){
                throw new RuntimeException("根据"+eaPayment.getId()+"TableId查询资金审批单费用明细集合为空！");
            }


            /*
             进入start相关事件调用WSDL在做处理
            */

                JSONObject jsonObject = new JSONObject();

                try {

                    //表头表体承载对象
                    JSONObject jsonHead = new JSONObject();

                    //根据表id查询任务记录最后审批人
                    ActZTask actZTask = iActZTaskService.getActZTaskByTableId(actBusiness.getProcInstId());

                    String userId = null;
                    int i = 0;
                    while (true){
                        i++;
                        userId = iActZTaskService.getActHiIdentitylinkById(actZTask.getProcInstId(), actZTask.getTaskId());

                        if(StrUtil.isNotEmpty(userId) || i==100){
                            break;
                        }
                        Thread.sleep(3000);
                    }
                    if(StrUtil.isEmpty(userId)){
                        throw new RuntimeException("根据表id查询任务记录最后审批人失败！");
                    }


                    /*
                    表头封装
                     */
                    jsonHead.put("bbje",eaPayment.getActualPayAmt());
                    // 币种=人民币-币种主键，直接取人民币主键
                    jsonHead.put("bzbm","1002Z0100000000001K1");
                    jsonHead.put("cjkbbje","0");
                    // 冲借款本币金额= -金额为0 否
                    jsonHead.put("cjkybje","0");
                    // 创建人=创建人-用户主键
                    jsonHead.put("creator",eaPayment.getCreateBy());
                    jsonHead.put("deptid",eaPayment.getDeptId());
                    // 报销人部门=报销人部门-组织_部门版本信息
                    jsonHead.put("deptid_v",eaPayment.getDeptId());
                    // 单据编号=单据编号
                    jsonHead.put("djbh",eaPayment.getBillNo());
                    // 单据大类=bx-bx
                    jsonHead.put("djdl","bx");
                    // 单据类型编码=264X-Cxx-ty-资金付款审批单:264X-Cxx-ty
                    jsonHead.put("djlxbm","264X-Cxx-ty");
                    // 单据日期=单据日期-2021-12-15 09:32:43
                    jsonHead.put("djrq", DateUtil.format(eaPayment.getBillDate(),"yyyy-MM-dd HH:mm:ss") );
                    // 单据状态=3-0=暂存，1=保存，2=审核，3=签字，-1=作废，
                    jsonHead.put("djzt",eaPayment.getState());
                    // 原费用承担单位=费用承担单位-组织
                    jsonHead.put("fydwbm",eaPayment.getCostCompCodeId());
                    // 费用承担单位=费用承担单位-组织_版本信息
                    jsonHead.put("fydwbm_v",eaPayment.getCostCompCodeId());
                    jsonHead.put("dr","0");
                    // 本币汇率=默认为1
                    jsonHead.put("bbhl","1");
                    jsonHead.put("dwbm",eaPayment.getCompanyCodeId());
                    // 报销人单位=报销人单位
                    jsonHead.put("dwbm_v",eaPayment.getCompanyCodeId());
                    // 附件张数=附件张数 否
                    jsonHead.put("fjzs","0");
                    // 原费用承担部门=费用承担部门-组织_部门
                    jsonHead.put("fydeptid",eaPayment.getCostDept());
                    // 费用承担部门=费用承担部门-组织_部门版本信息
                    jsonHead.put("fydeptid_v",eaPayment.getCostDept());
                    // 供应商=供应商-收款对象为供应商，供应商必填 否
                    jsonHead.put("hbbm",eaPayment.getRecPersonId());
                    // 还款本币金额= -金额为0 否
                    jsonHead.put("hkbbje","0");
                    jsonHead.put("hkybje","0");
                    // 报销人=报销人
                    jsonHead.put("jkbxr",eaPayment.getPersonId());
                    // 结算方式=支付方式
                    jsonHead.put("jsfs",eaPayment.getPaymentMethod());
                    // 签字人=最后审批人(财务)
                    jsonHead.put("jsr",actZTask.getOwnerId());
                    // 会计年度=单据日期年度
                    jsonHead.put("kjnd","");
                    // 会计期间=单据日期月份
                    jsonHead.put("kjqj","");
                    // 录入人=录入人-用户主键
                    jsonHead.put("operator",eaPayment.getCreateBy());
                    // 支付状态=3-3=支付完成
                    jsonHead.put("payflag","3");
                    // 支付人=最后审批人(财务)
                    jsonHead.put("payman",actZTask.getOwnerId());
                    jsonHead.put("paytarget",eaPayment.getTransactionType());
                    // pk_billtype=264X-264X
                    jsonHead.put("pk_billtype","264X");
                    // 集团=集团
                    jsonHead.put("pk_group","0001A110000000000CLJ");
                    // 财务组织=费用承担单位
                    jsonHead.put("pk_fiorg",eaPayment.getCostCompCodeId());
                    // 报销单标识 =主表主键-n
                    jsonHead.put("pk_jkbx","");
                    // 原报销单位=费用承担单位
                    jsonHead.put("pk_org",eaPayment.getCostCompCodeId());
                    // 报销单位=费用承担单位
                    jsonHead.put("pk_org_v",eaPayment.getCostCompCodeId());
                    // 原付款单位=费用承担单位
                    jsonHead.put("pk_payorg",eaPayment.getCostCompCodeId());
                    // 付款单位=费用承担单位
                    jsonHead.put("pk_payorg_v",eaPayment.getCostCompCodeId());
                    // 交易类型=NC交易类型主键
                    jsonHead.put("pk_tradetypeid","1001A11000000011GUC5");
                    jsonHead.put("receiver",eaPayment.getRecPersonId());
                    // 审批状态=审批通过-0=审批未通过，1=审批通过，2=审批进行中，3=提交，-1=自由，
                    jsonHead.put("spzt","-1");
                    // 生效标志=1-0=未生效，1=已生效，
                    jsonHead.put("sxbz","1");
                    // 合计金额=实际付款金额
                    jsonHead.put("total",eaPayment.getActualPayAmt());
                    // 原币金额=实际付款金额
                    jsonHead.put("ybje",eaPayment.getActualPayAmt());
                    // 审批人=最后审批人(财务)-用户主键
                    jsonHead.put("approver",actZTask.getOwnerId());
                    jsonHead.put("zfbbje",eaPayment.getActualPayAmt());
                    jsonHead.put("zfybje",eaPayment.getActualPayAmt());
                    // 事由=事由
                    jsonHead.put("zy",eaPayment.getCause());
                    // 收支项目=费用项目
                    jsonHead.put("szxmid",eaPayment.getIndexId());
                    //最后审批人编码
                    jsonHead.put("actionCode", "APPROVE" + userId);

                    jsonObject.put("head",jsonHead);
                    /*
                    表头封装结束
                     */


                    /*
                    表体封装
                     */
                    JSONArray jsonArrayBody = new JSONArray();
                    for (int a = 0; a < eaBookDetails.size(); a++) {

                        //获取费用明细
                        EaBookDetail eaBookDetail = eaBookDetails.get(a);
                        EaListenerUtil.objectDefault(eaBookDetail, EaBookDetail.class);

                        List<Map<String, Object>> billDetailList=null;

                        try {
                            //获取根据发票id获取发票明细集合
                            billDetailList = iEaBillService.getBillDetailList(eaBookDetail.getFpid());
                        }catch (Exception e){
                            throw new RuntimeException("获取发票明细失败!(StackTrace="+EaListenerUtil.formatStackTrace(e)+")");
                        }

                        //表体封装
                        if (billDetailList!=null||billDetailList.size()>0) {
                            try{
                                JSONArray detaijsonObject = JSON.parseArray(JSON.toJSONString(billDetailList));
                                bodySet(eaPayment, eaBookDetail, detaijsonObject, jsonArrayBody);
                            }catch (Exception e){
                                throw new RuntimeException("fybx表体封装错误!(StackTrace="+EaListenerUtil.formatStackTrace(e)+")");
                            }
                        } else {
                            throw new RuntimeException("获取发票明细空！");
                        }


                    }

                    jsonObject.put("body", jsonArrayBody);
                    /*
                    表体封装结束
                     */


                    //调用WSDL
                    WSVO wsvo = NCWebService.sendToWS(nCUrl, WSEnum.CASHPAYMENTBILL, jsonObject.toJSONString());

                    //日志保存
                    if(!wsvo.getStatus()){
                        throw new RuntimeException(wsvo.getMessage());
                    }
                    sysInterfaceLog.setState("1");
                    sysInterfaceLog.setDisposeState("0");
                    sysInterfaceLog.setResult(wsvo.getMessage());
                } catch (Exception e) {
                    sysInterfaceLog.setState("0");
                    sysInterfaceLog.setDisposeState("1");
                    sysInterfaceLog.setResult(e.getMessage());
                }
        sysInterfaceLog.setContent(jsonObject.toJSONString());
        sysInterfaceLog.setCreateTime(new DateTime());
        return sysInterfaceLog;
    }



    /**
     * @Description: 设置表体
     * @author: CYS
     * @date: 2022/2/23 11:12
     * @param eaPayment:
     * @param eaBookDetail:
     * @param detaijsonArray:
     * @param jsonArrayBody:
     * @Return: com.alibaba.fastjson.JSONObject
     */
    private  void bodySet(EaPayment eaPayment, EaBookDetail eaBookDetail, JSONArray detaijsonArray, JSONArray jsonArrayBody)throws Exception{
        for (int a=0;a<detaijsonArray.size();a++) {
            JSONObject jsonBody = new JSONObject();
            //发票明细行税率
            BigDecimal taxRate =detaijsonArray.getJSONObject(a).getBigDecimal("taxRate").divide(new BigDecimal("100"));            //发票明细行实际报销金额
            //实际报销金额
            BigDecimal actualEaAmt=null;
            //税额
            BigDecimal tax=null;

            //飞机发票类型
            if(eaBookDetail.getType().equals("10506")){
                actualEaAmt=eaBookDetail.getActualEaAmt();
                //航空票价
                BigDecimal fare= detaijsonArray.getJSONObject(a).getBigDecimal("fare");
                //航空燃油费
                BigDecimal fuelSurcharge= detaijsonArray.getJSONObject(a).getBigDecimal("fuelSurcharge");

                tax = (fare.add(fuelSurcharge)).divide((new BigDecimal("1").add(taxRate)),2,RoundingMode.HALF_UP).multiply(taxRate);
                //火车发票类型
            }else if(eaBookDetail.getType().equals("10503")) {
                actualEaAmt=eaBookDetail.getActualEaAmt();
                tax = actualEaAmt.divide((new BigDecimal("1").add(taxRate)),2, RoundingMode.HALF_UP).multiply(taxRate);

            }else {
                //发票明细行实际报销金额
                BigDecimal totalAmount=detaijsonArray.getJSONObject(a).getBigDecimal("totalAmount");
                //发票明细行实际报销金额对发票总金额占比
                BigDecimal moneyNProportion=totalAmount.divide(eaBookDetail.getAmount(),2, RoundingMode.HALF_UP);
                //发票实际报销金额
                actualEaAmt=eaBookDetail.getActualEaAmt().multiply(moneyNProportion);

                tax = actualEaAmt.divide((new BigDecimal("1").add(taxRate)),2, RoundingMode.HALF_UP).multiply(taxRate);
            }

            //无税金额
            BigDecimal taxless = actualEaAmt.subtract(tax);

            // 合计金额=实际报销金额
            jsonBody.put("amount",actualEaAmt);
            // 报销本币金额=实际付款金额
            jsonBody.put("bbje",actualEaAmt);
            // 本币余额= -金额为0 否
            jsonBody.put("bbye", "0");
            // 冲借款本币金额= -金额为0 否
            // 冲借款本币金额= -金额为0 否
            jsonBody.put("cjkbbje", "0");
            // 冲借款本币金额= -金额为0 否
            jsonBody.put("cjkybje", "0");
            // 发票类型=发票类型表体自定义项12
            jsonBody.put("defitem12", detaijsonArray.getJSONObject(a).getString("fpTypeName"));
            // 不含税金额=不含税金额
            jsonBody.put("defitem13", taxless);
            // 税率=税率-转成NC的税码主键
            jsonBody.put("defitem14", detaijsonArray.getJSONObject(a).getString("taxCode"));
            // 税额
            jsonBody.put("defitem15", tax);
            if(eaBookDetail.getFygsr().equals(eaPayment.getPersonId())){
                // 报销人部门=表体费用归属人部门
                jsonBody.put("deptid",eaPayment.getDeptId());
            }else{
                // 报销人部门=表体费用归属人部门
                jsonBody.put("deptid", iNcBdPsnjobService.getById(eaBookDetail.getPsnjobId()).getPkDept());
            }
            // 删除标志=0
            jsonBody.put("dr", "0");
            // 报销人单位 =表体费用归属人单位
            jsonBody.put("dwbm",eaPayment.getCostCompCodeId());
            // 供应商=供应商-收款对象为供应商，供应商必填 否
            jsonBody.put("hbbm", eaPayment.getSupplier());
            // 还款本币金额= -金额为0
            jsonBody.put("hkbbje", "0");
            // 还款原币金额= -金额为0
            jsonBody.put("hkybje", "0");
            // 借款报销人=表体费用归属人
            jsonBody.put("jkbxr", eaBookDetail.getFygsr());
            // 收款对象=直接取表头收款对象
            jsonBody.put("paytarget", eaPayment.getTransactionType());
            // 报销单业务行标识=子表主键
            jsonBody.put("pk_busitem", "");
            jsonBody.put("pk_jkbx", "");
            // 报销类型=消费类型-n
            jsonBody.put("pk_reimtype", eaBookDetail.getKind());
            // 收款人=收款人-收款对象为员工，收款人必填
            // 收款人=直接取表头收款人
            jsonBody.put("receiver",eaPayment.getRecPersonId());
            // 行号=行号-n
            jsonBody.put("rowno", jsonArrayBody.size()+1);
            // 收支项目=费用项目
            jsonBody.put("szxmid",eaPayment.getIndexId());
            // 原币金额=实际报销金额
            jsonBody.put("ybje",actualEaAmt);
            // 支付本币金额 =实际付款金额
            jsonBody.put("zfbbje",actualEaAmt);
            // 支付金额=实际报销金额
            jsonBody.put("zfybje",  actualEaAmt);
            jsonBody.put("zyx12",eaBookDetail.getType());

            jsonArrayBody.add(jsonBody);
        }

    }



}
